﻿using AMMVVMLibrary.Portable;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace AMMVVMLibrary.WP8
{
    public class NavigationService : INavigationService
    {
        public NavigationService(Assembly assembly = null)
        {
            _assembly = assembly;
            //ViewModelRouting = null;
        }

        /// <summary> 
        /// Gets a value indicating whether can go back. 
        /// </summary> 
        public bool CanGoBack
        {
            get
            {
                return RootFrame.CanGoBack;
            }
        }

        /// <summary> 
        /// Gets the root frame. 
        /// </summary> 
        private Frame RootFrame
        {
            get { return Application.Current.RootVisual as Frame; }
        }

        public Assembly _assembly;

        /// <summary> 
        /// Decodes the navigation parameter. 
        /// </summary> 
        /// <typeparam name="TJson">The type of the json.</typeparam> 
        /// <param name="context">The context.</param> 
        /// <returns>The json result.</returns> 
        public static TJson DecodeNavigationParameter<TJson>(NavigationContext context)
        {
            if (context.QueryString.ContainsKey("param"))
            {
                var param = context.QueryString["param"];
                return string.IsNullOrWhiteSpace(param) ? default(TJson) : JsonConvert.DeserializeObject<TJson>(param);
            }

            throw new KeyNotFoundException();
        }

        /// <summary> 
        /// The go back. 
        /// </summary> 
        public void GoBack()
        {
            RootFrame.GoBack();
        }

        /// <summary> 
        /// Navigates the specified parameter. 
        /// </summary> 
        /// <typeparam name="TDestinationViewModel">The type of the destination view model.</typeparam> 
        /// <param name="parameter">The parameter.</param> 
        public void Navigate<TDestinationViewModel>(object parameter)
        {
            var navParameter = string.Empty;
            if (parameter != null)
            {
                navParameter = "?param=" + JsonConvert.SerializeObject(parameter);
            }

            string dest = null;
            if (ViewModelRouting != null && ViewModelRouting.ContainsKey(typeof(TDestinationViewModel)))
                dest = ViewModelRouting[typeof(TDestinationViewModel)];
            else if (_assembly != null)
                dest = ResolveView(typeof(TDestinationViewModel));
            else
                throw new ArgumentException("Either specify the ViewModelRouting or pass your Assembly for automatic view resolving.");

            this.RootFrame.Navigate(new Uri("/" + dest + navParameter, UriKind.Relative));
        }

        /// <summary>
        /// Resolve the view name automagically. Needs more testing
        /// </summary>
        /// <param name="viewModelType"></param>
        /// <returns></returns>
        public string ResolveView(Type viewModelType)
        {
            var viewModelName = viewModelType.Name;
            var viewModelSplit = viewModelName.Split(new string[] { "ViewModel" }, StringSplitOptions.RemoveEmptyEntries);
            var pageName = viewModelSplit.First();
            return "Views/" + pageName + ".xaml";
        }

        /// <summary>
        /// The view model routing. 
        /// Example
        /// = new Dictionary<Type, Type>() 
        /// { 
        ///     { typeof(TitlesViewModel), "View/TitlesPage.xaml" }, 
        ///     { typeof(TitleDetailsViewModel), "View/TitleDetailsPage.xaml" } 
        /// }; 
        /// </summary>
        public IDictionary<Type, string> ViewModelRouting
        {
            get;
            set;
        }
    }
}
